package com.yami.shop.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.enums.AirdropRecordEnum;
import com.yami.shop.bean.event.AirDropSuccessEvent;
import com.yami.shop.bean.event.QualificationEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.SendUserDropsParam;
import com.yami.shop.bean.vo.MysteryBoxExtensionVo;
import com.yami.shop.bean.vo.PersonNft;
import com.yami.shop.bean.vo.flow.MemberDealVO;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.dao.AirdropTaskConditionsMapper;
import com.yami.shop.dao.AirdropTaskMapper;
import com.yami.shop.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * (TzAirdropTask)表服务实现类
 *
 * @author makejava
 * @since 2023-05-22 18:29:22
 */
@Slf4j
@Service("airdropTaskService")
@RequiredArgsConstructor
public class AirdropTaskServiceImpl extends ServiceImpl<AirdropTaskMapper, AirdropTask> implements AirdropTaskService {

    private final AirdropTaskMapper airdropTaskMapper;

    private final AirdropTaskConditionsMapper airdropTaskConditionsMapper;

    private final UserService userService;

    private final CustomerAnalysisService customerAnalysisService;

    private final ShopDetailService shopDetailService;

    private final ProductService productService;

    private final ChannelUserRelationRecordService channelUserRelationRecordService;

    private final ApplicationEventPublisher eventPublisher;

    private final UserAirdropService userAirdropService;


    @Override
    public IPage<AirdropTask> page(PageParam<AirdropTask> page, AirdropTask airdropTask) {
        IPage<AirdropTask> airdropTaskPage = airdropTaskMapper.getAirdropTaskPage(page, airdropTask);
        if (!airdropTaskPage.getRecords().isEmpty()) {
            airdropTaskPage.getRecords().stream().forEach(task -> {
                List<AirdropTaskConditions> airdropTaskConditions = airdropTaskConditionsMapper.selectList(new LambdaQueryWrapper<AirdropTaskConditions>().eq(AirdropTaskConditions::getTaskId, task.getAirdropTaskId()));
                task.setAirdropTaskConditions(airdropTaskConditions);
            });
        }
        return airdropTaskPage;
    }

    @Override
    public List<User> getDropUserInfoList(List<AirdropTaskConditions> conditions, String articleIds, String articleType, Long shopId) {
        Set<String> allUserIds = new HashSet<>();
        if (conditions.isEmpty()) {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            if (articleType.equals("1")|| articleType.equals("2") || articleType.equals("3")) {
                queryWrapper.select("user_id").eq("status", 1);
            } else {
                queryWrapper.select("user_id").eq("status", 1).isNotNull("real_name");
            }

            List<User> users = userService.list(queryWrapper);
            allUserIds = users.stream().map(User::getUserId).collect(Collectors.toSet());
        } else {
            for (AirdropTaskConditions condition : conditions) {
                Set<String> ids = filterByCondition(condition, shopId, articleType);
                if (allUserIds.isEmpty()) {
                    allUserIds.addAll(ids);
                    continue;
                }
                if (condition.getLogicalOperation() == 2) {
                    // 或 并集
                    allUserIds.addAll(ids);
                }
                if (condition.getLogicalOperation() == 1) {
                    // 且 交集
                    allUserIds.retainAll(ids);
                }
            }
        }
        List<User> userByUserIds = new ArrayList<>();
        if (!allUserIds.isEmpty()) {
            String[] articleIdArr = articleIds.split(",");
            Set<String> newDropUserIds = new HashSet<>();
            for (String userId : allUserIds) {
                for (String articleId : articleIdArr) {
                    if (articleType.equals("0")) {
                        Product productInfo = productService.getProductInfo(Long.valueOf(articleId));
                        // 过滤没有链上地址的用户
                        if (channelUserRelationRecordService.isHasDTCAddress(userId, productInfo.getChain(), productInfo.getChannelCode())) {
                            newDropUserIds.add(userId);
                        }
                    }
                    if (articleType.equals("1") || articleType.equals("2") || articleType.equals("3")) {
                        newDropUserIds.add(userId);
                    }
                }
            }
            if (!newDropUserIds.isEmpty()) {
                userByUserIds = userService.getUserByUserIds(new ArrayList<>(newDropUserIds));
            }
        }
        return userByUserIds;
    }

    @Override
    public void airdropTask(Long airdropTaskId) {
        List<AirdropTask> airdropTasks = new ArrayList<>();
        if (airdropTaskId == null) {
            airdropTasks = airdropTaskMapper.selectList(new LambdaQueryWrapper<AirdropTask>().eq(AirdropTask::getStatus, 0).le(AirdropTask::getExecuteTime, new Date()));
        }
        if (airdropTaskId != null) {
            AirdropTask airdropTask = airdropTaskMapper.selectById(airdropTaskId);
            if (airdropTask.getStatus() != 0) {
                return;
            }
            airdropTasks.add(airdropTask);
        }
        log.info("查询到的待执行空投任务有{}个", airdropTasks.size());
        if (CollectionUtils.isEmpty(airdropTasks)) {
            log.error("未查询到需要执行的空投任务！");
            return;
        }
        for (AirdropTask airdropTask : airdropTasks) {
            if (RedisUtil.hasKey("airdropTasks:" + airdropTask.getAirdropTaskId())) {
                log.error("Id为{}空投任务已经在执行中！", airdropTask.getAirdropTaskId());
            }
            RedisUtil.set("airdropTasks:" + airdropTask.getAirdropTaskId(), "true", 10);
            log.info("执行的空投记录为{}", airdropTask.getAirdropTaskId());
            String[] articleIds = airdropTask.getArticleIds().split(",");
            // 获取空投条件
            List<AirdropTaskConditions> airdropTaskConditions = airdropTaskConditionsMapper.selectList(new LambdaQueryWrapper<AirdropTaskConditions>().eq(AirdropTaskConditions::getTaskId, airdropTask.getAirdropTaskId()));
            // 获取符合空投条件的有效会员
            List<String> dropUserList = getDropUserIdList(airdropTaskConditions, airdropTask.getDropShopId(), airdropTask.getArticleType());
            log.info("执行的空投的用户个数为{}", dropUserList.size());
            // 检查用户链上地址
            Set<String> newDropUserIds = new HashSet<>();
            for (String userId : dropUserList) {
                for (String articleId : articleIds) {
                    String prodName = "";
                    String boxName = "";
                    Set<String> userIds = new HashSet<>();
                    List<SendUserDropsParam> dropsParamList = new ArrayList<>();
                    SendUserDropsParam dropsParam = new SendUserDropsParam();
                    dropsParam.setTargetId(Long.valueOf(articleId));
                    dropsParam.setNums(1);
                    dropsParam.setType(Integer.valueOf(airdropTask.getArticleType()));
                    dropsParamList.add(dropsParam);
                    // 空投商品基本信息校验
                    if (airdropTask.getArticleType().equals("0")) {
                        Product productInfo = productService.getProductInfo(Long.valueOf(articleId));
                        // 过滤没有链上地址的用户
                        if (channelUserRelationRecordService.isHasDTCAddress(userId, productInfo.getChain(), productInfo.getChannelCode())) {
                            newDropUserIds.add(userId);
                            userIds.add(userId);
                            eventPublisher.publishEvent(new AirDropSuccessEvent(
                                    new ArrayList<>(userIds),
                                    dropsParamList,
                                    2,
                                    airdropTask.getDropShopId(),
                                    Integer.valueOf(airdropTask.getArticleType()),
                                    airdropTask.getAirdropTaskId(),null));
                        }
                    }

                    // 空投盲盒基本信息校验
                    if (airdropTask.getArticleType().equals("1")) {
                        eventPublisher.publishEvent(new AirDropSuccessEvent(Collections.singletonList(userId), dropsParamList, 2, airdropTask.getDropShopId(), Integer.valueOf(airdropTask.getArticleType()), airdropTask.getAirdropTaskId(),null));
                    }
                    // 空投商品优先购资格
                    if (airdropTask.getArticleType().equals("2")) {
                        eventPublisher.publishEvent(new QualificationEvent(userId, Long.valueOf(articleId), null, 1L, 1L, 2, airdropTask.getAirdropTaskId().toString(), ObjectUtil.isNotNull(airdropTask.getEffectiveTime()) ? airdropTask.getEffectiveTime() : null));
                        UserAirdrop record = createUserAirdrop(userId, prodName, articleId, airdropTask, Integer.valueOf(airdropTask.getArticleType()), AirdropRecordEnum.SUCCESS.value());
                        userAirdropService.save(record);
                    }
                    // 空投盲盒优先购资格
                    if (airdropTask.getArticleType().equals("3")) {
                        eventPublisher.publishEvent(new QualificationEvent(userId, null, Long.valueOf(articleId), 1L, 1L, 2, airdropTask.getAirdropTaskId().toString(), ObjectUtil.isNotNull(airdropTask.getEffectiveTime()) ? airdropTask.getEffectiveTime() : null));
                        UserAirdrop record = createUserAirdrop(userId, boxName, articleId, airdropTask, Integer.valueOf(airdropTask.getArticleType()), AirdropRecordEnum.SUCCESS.value());
                        userAirdropService.save(record);
                    }
                }
            }
            if (airdropTask.getArticleType().equals("0") ) {
                if (newDropUserIds.isEmpty()) {
                    // 更新任务状态为已执行并补充错误信息
                    updateAirdropTaskStatus(airdropTask.getAirdropTaskId(), 1, "未查询到空投用户的链上地址", newDropUserIds.size(), 0);
                    continue;
                } else {
                    // 更新空投任务已执行状态
                    updateAirdropTaskStatus(airdropTask.getAirdropTaskId(), 1, null, dropUserList.size(), dropUserList.size());
                }
            }
            if (airdropTask.getArticleType().equals("1") || airdropTask.getArticleType().equals("2") || airdropTask.getArticleType().equals("3")) {
                // 更新空投任务已执行状态
                updateAirdropTaskStatus(airdropTask.getAirdropTaskId(), 1, null, dropUserList.size(), dropUserList.size());
            }
        }
    }

    // 更新任务状态
    private void updateAirdropTaskStatus(Long taskId, Integer status, String errorInfo, Integer total, Integer successNum) {
        AirdropTask newAirdropTask = new AirdropTask();
        newAirdropTask.setAirdropTaskId(taskId);
        newAirdropTask.setStatus(status);
        newAirdropTask.setUpdateTime(new Date());
        newAirdropTask.setReason(errorInfo);
        newAirdropTask.setTotal(total);
        newAirdropTask.setSuccessNum(successNum);
        airdropTaskMapper.updateById(newAirdropTask);
    }

    // 创建UserAirdrop对象
    private UserAirdrop createUserAirdrop(String userId, String articleName, String articleId, AirdropTask airdropTask, Integer articleType, Integer status) {
        UserAirdrop record = new UserAirdrop();
        record.setAirDropId(IdUtil.getSnowflakeNextId());
        record.setArticleName(articleName);
        record.setArticleId(articleId);
        record.setArticleType(articleType);
        record.setUserId(userId);
        record.setNum(1);
        record.setSuccessNum(1);
        record.setBusinessType(2);
        record.setDropShopId(airdropTask.getDropShopId());
        record.setStatus(status);
        record.setAirdropBusinessId(airdropTask.getAirdropTaskId());
        record.setCreateTime(new Date());
        return record;
    }

    public List<String> getDropUserIdList(List<AirdropTaskConditions> conditions, Long dropShopId, String articleType) {
        Set<String> allUserIds = new HashSet<>();
        if (conditions.isEmpty()) {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            if (articleType.equals("1")|| articleType.equals("2") || articleType.equals("3")) {
                queryWrapper.select("user_id").eq("status", 1);
            } else {
                queryWrapper.select("user_id").eq("status", 1).isNotNull("real_name");
            }
            List<User> users = userService.list(queryWrapper);
            allUserIds = users.stream().map(User::getUserId).collect(Collectors.toSet());
        } else {
            for (AirdropTaskConditions condition : conditions) {
                Set<String> ids = filterByCondition(condition, dropShopId, articleType);
                if (allUserIds.isEmpty()) {
                    allUserIds.addAll(ids);
                    continue;
                }
                if (condition.getLogicalOperation() == 2) {
                    // 或 并集
                    allUserIds.addAll(ids);
                }
                if (condition.getLogicalOperation() == 1) {
                    // 且 交集
                    allUserIds.retainAll(ids);
                }
            }
        }
        return allUserIds.stream().collect(Collectors.toList());
    }

    // 优化后的方法，根据条件过滤用户ID
    private Set<String> filterByCondition(AirdropTaskConditions condition, Long dropShopId, String articleType) {
        switch (condition.getFieldName()) {
            case "注册时间":
                return filterByRegistrationTime(condition, articleType);
            case "支付金额":
            case "支付次数":
                return filterByPaymentData(condition, dropShopId);
            case "持有艺术品":
                return filterByArtworkOwnership(condition);
            default:
                return new HashSet<>();
        }
    }

    // 过滤注册时间条件
    private Set<String> filterByRegistrationTime(AirdropTaskConditions condition, String articleType) {
        // 1大于等于 2大于 3等于 4小于等于 5小于
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (articleType.equals("1")|| articleType.equals("2") || articleType.equals("3")) {
            queryWrapper.select("user_id").eq("status", 1);
        } else {
            queryWrapper.select("user_id").eq("status", 1).isNotNull("real_name");
        }
        if (condition.getCond() == 1) {
            queryWrapper.ge("user_regtime", condition.getFieldValue());
        } else if (condition.getCond() == 2) {
            Date date = DateUtil.parse(condition.getFieldValue());
            Date endOfDay = DateUtil.endOfDay(date);
            String formatDateTime = DateUtil.formatDateTime(endOfDay);
            queryWrapper.gt("user_regtime", formatDateTime);
        } else if (condition.getCond() == 3) {
            Date date = DateUtil.parse(condition.getFieldValue());
            Date beginOfDay = DateUtil.beginOfDay(date);
            Date endOfDay = DateUtil.endOfDay(date);
            String beginOfDateTime = DateUtil.formatDateTime(beginOfDay);
            String endOfDateTime = DateUtil.formatDateTime(endOfDay);
            queryWrapper.between("user_regtime", beginOfDateTime, endOfDateTime);
        } else if (condition.getCond() == 4) {
            queryWrapper.le("user_regtime", condition.getFieldValue());
        } else if (condition.getCond() == 5) {
            Date date = DateUtil.parse(condition.getFieldValue());
            Date beginOfDay = DateUtil.beginOfDay(date);
            String formatDateTime = DateUtil.formatDateTime(beginOfDay);
            queryWrapper.lt("user_regtime", formatDateTime);
        }
        List<User> users = userService.list(queryWrapper);
        return users.stream().map(User::getUserId).collect(Collectors.toSet());
    }

    // 过滤支付金额和支付次数条件
    private Set<String> filterByPaymentData(AirdropTaskConditions condition, Long dropShopId) {
        List<MemberDealVO> memberPayDataForDrop = customerAnalysisService.getMemberPayDataForDrop(dropShopId);
        List<MemberDealVO> collect = memberPayDataForDrop.stream().filter(personNft -> {
            if (condition.getFieldName().equals("支付金额")) {
                return checkCondition(personNft.getPayAmount(), condition);
            } else if (condition.getFieldName().equals("支付次数")) {
                return checkCondition(personNft.getPayOrderNum().doubleValue(), condition);
            }
            return false;
        }).collect(Collectors.toList());
        return collect.stream().map(MemberDealVO::getUserId).collect(Collectors.toSet());
    }

    // 检查条件是否满足
    private boolean checkCondition(Double value, AirdropTaskConditions condition) {
        int cond = condition.getCond().intValue();
        int fieldValue = Integer.parseInt(condition.getFieldValue());
        return (cond == 1 && value >= fieldValue) || (cond == 2 && value > fieldValue) || (cond == 3 && value == fieldValue) || (cond == 4 && value <= fieldValue) || (cond == 5 && value < fieldValue);
    }

    // 过滤持有艺术品条件
    private Set<String> filterByArtworkOwnership(AirdropTaskConditions condition) {
        List<PersonNft> userIdByProductId = airdropTaskMapper.getUserIdByProductId(condition.getProdId());
        List<PersonNft> collect = userIdByProductId.stream().filter(personNft -> checkCondition(personNft.getHoldNum().doubleValue(), condition)).collect(Collectors.toList());
        return collect.stream().map(PersonNft::getUserId).collect(Collectors.toSet());
    }
}

